package com.my.blog.website.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.my.blog.website.constant.WebConst;
import com.my.blog.website.dao.ContentVoMapper;
import com.my.blog.website.dao.MetaVoMapper;
import com.my.blog.website.dto.Types;
import com.my.blog.website.exception.TipException;
import com.my.blog.website.modal.Vo.ContentVo;
import com.my.blog.website.modal.Vo.MetaVo;
import com.my.blog.website.modal.Vo.RelationshipVoKey;
import com.my.blog.website.service.IContentService;
import com.my.blog.website.service.IMetaService;
import com.my.blog.website.service.IRelationshipService;
import com.my.blog.website.utils.DateKit;
import com.my.blog.website.utils.TaleUtils;
import com.my.blog.website.utils.Tools;
import com.vdurmont.emoji.EmojiParser;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;

/**
 * Created by Administrator on 2017/3/13 013.
 */
@Service
public class ContentServiceImpl implements IContentService {
    private static final Logger LOGGER = LoggerFactory.getLogger(ContentServiceImpl.class);

    @Resource
    private ContentVoMapper contentDao;

    @Resource
    private MetaVoMapper metaDao;

    @Resource
    private IRelationshipService relationshipService;

    @Resource
    private IMetaService metasService;

    @Override
    @Transactional
    public String publish(ContentVo contents) {
        if (null == contents) {
            return "文章对象为空";
        }
        if (StringUtils.isBlank(contents.getTitle())) {
            return "文章标题不能为空";
        }
        if (StringUtils.isBlank(contents.getContent())) {
            return "文章内容不能为空";
        }
        int titleLength = contents.getTitle().length();
        if (titleLength > WebConst.MAX_TITLE_COUNT) {
            return "文章标题过长";
        }
        int contentLength = contents.getContent().length();
        if (contentLength > WebConst.MAX_TEXT_COUNT) {
            return "文章内容过长";
        }
        if (null == contents.getAuthorId()) {
            return "请登录后发布文章";
        }
        if (StringUtils.isNotBlank(contents.getSlug())) {
            if (contents.getSlug().length() < 5) {
                return "路径太短了";
            }
            if (!TaleUtils.isPath(contents.getSlug())) {
                return "您输入的路径不合法";
            }
           /* ContentVoExample contentVoExample = new ContentVoExample();
            contentVoExample.createCriteria().andTypeEqualTo(contents.getType()).andStatusEqualTo(contents.getSlug());
            long count = contentDao.countByExample(contentVoExample);*/
            Example example = new Example(ContentVo.class);
            Example.Criteria criteria = example.createCriteria();
            criteria.andEqualTo("type",contents.getType()).andEqualTo("slug",contents.getSlug());

            int count = contentDao.selectCountByExample(example);
            if (count > 0) {
                return "该路径已经存在，请重新输入";
            }
        } else {
            contents.setSlug(null);
        }

        //To replace all the emoji's unicodes found in a string by their aliases, use EmojiParser#parseToAliases(String)
        //https://github.com/vdurmont/emoji-java
        contents.setContent(EmojiParser.parseToAliases(contents.getContent()));

        int time = DateKit.getCurrentUnixTime();
        contents.setCreated(time);
        contents.setModified(time);
        contents.setHits(0);
        contents.setCommentsNum(0);

        contents = resetContentVo(contents);

        contentDao.insert(contents);
        Integer cid = contents.getCid();

        metasService.saveMetas(contents.getAuthorId(), cid, contents.getTags(), Types.TAG.getType(),contents.getStatus(),Types.DRAFT.getType());
        metasService.saveMetas(contents.getAuthorId(), cid, contents.getCategories(), Types.CATEGORY.getType(),contents.getStatus(),Types.DRAFT.getType());
        return WebConst.SUCCESS_RESULT;
    }

    @Override
    public PageInfo<ContentVo> getContents(Integer p, Integer limit) {
        return getContents(null,p,limit);
    }

    @Override
    public PageInfo<ContentVo> getContents(Integer uid,Integer p, Integer limit) {
        LOGGER.debug("Enter getContents method");
//        Example example = new Example(ContentVo.class);
//        Example.Criteria criteria = example.createCriteria();
//        if (null!=uid){
//            criteria.andEqualTo("authorId",uid);
//        }
//        criteria.andEqualTo("type",Types.ARTICLE.getType()).andEqualTo("status",Types.PUBLISH.getType());
//        example.setOrderByClause("modified desc");
        PageHelper.startPage(p, limit);
//        List<ContentVo> data = contentDao.selectByExample(example);

        ContentVo contentVo = new ContentVo();
        if (null != uid){
            contentVo.setAuthorId(uid);
        }
        contentVo.setType(Types.ARTICLE.getType());
        contentVo.setStatus(Types.PUBLISH.getType());
        List<ContentVo> data = contentDao.selectByCondition(contentVo);

        PageInfo<ContentVo> pageInfo = new PageInfo<>(data);
        LOGGER.debug("Exit getContents method");
        return pageInfo;
    }

    @Override
    public ContentVo getContents(String id) {
        if (StringUtils.isNotBlank(id)) {
            if (Tools.isNumber(id)) {
                ContentVo contentVo = contentDao.selectByPrimaryKey(Integer.valueOf(id));
                if (contentVo != null) {
                    contentVo.setHits(contentVo.getHits() + 1);
                    contentDao.updateByPrimaryKey(contentVo);
                }
                return contentVo;
            } else {
               /* ContentVoExample contentVoExample = new ContentVoExample();
                contentVoExample.createCriteria().andSlugEqualTo(id);
                List<ContentVo> contentVos = contentDao.selectByExampleWithBLOBs(contentVoExample);*/
                Example example = new Example(ContentVo.class);
                Example.Criteria criteria = example.createCriteria();
                criteria.andEqualTo("slug",id);
                List<ContentVo> contentVos = contentDao.selectByExample(example);

                if (contentVos.size() != 1) {
                    LOGGER.info("query param:{},result={}", id,contentVos);
                    throw new TipException("query content by id and return is not one");
                }
                return contentVos.get(0);
            }
        }
        return null;
    }

    /**
     * 第一版，存在bug：一个分类或者标签查询会漏掉有多个标签的文章，废弃
     *
     * @param name name
     * @param type type
     * @param page
     * @param limit
     * @return
     */
    /*@Override
    public PageInfo<ContentVo> getContents(String name,String type,Integer page,Integer limit) {
        if (StringUtils.isNotBlank(name) && StringUtils.isNotBlank(type)) {
            ContentVoExample contentVoExample = new ContentVoExample();
            ContentVoExample.Criteria criteria = contentVoExample.createCriteria();
            criteria.andCidIsNotNull().andStatusEqualTo(Types.PUBLISH.getType());
            if (Types.CATEGORY.getType().equalsIgnoreCase(type)){
                criteria.andCategoriesEqualTo(name);
            }else{
                criteria.andTagsEqualTo(name);
            }
            contentVoExample.setOrderByClause("modified desc");

            PageHelper.startPage(page,limit);
            List<ContentVo> contentVos = contentDao.selectByExampleWithBLOBs(contentVoExample);
            return new PageInfo<>(contentVos);
        }
        return null;
    }*/

    @Override
    public PageInfo<ContentVo> getContents(String name,String type,Integer page,Integer limit) {
        return getContents(null, name, type, page, limit);
    }

    /**
     * 第二版，修正bug
     *
     * @param name name
     * @param type type
     * @param page
     * @param limit
     * @return
     */
    @Override
    public PageInfo<ContentVo> getContents(Integer uid, String name,String type,Integer page,Integer limit) {
        if (StringUtils.isNotBlank(name) && StringUtils.isNotBlank(type)) {
            ContentVo contentVo = new ContentVo();
            contentVo.setStatus(Types.PUBLISH.getType());
            if (Types.CATEGORY.getType().equalsIgnoreCase(type)){
                contentVo.setCategories(name);
            }else{
                contentVo.setTags(name);
            }
            contentVo.setAuthorId(uid);

            PageHelper.startPage(page,limit);
            List<ContentVo> contentVos = contentDao.selectByCondition(contentVo);
            return new PageInfo<>(contentVos);
        }
        return null;
    }

    @Override
    public void updateContentByCid(ContentVo contentVo) {
        if (null != contentVo && null != contentVo.getCid()) {
            contentDao.updateByPrimaryKeySelective(contentVo);
        }
    }

    @Override
    public PageInfo<ContentVo> getArticles(Integer mid, int page, int limit) {
        int total = metaDao.countWithSql(mid);
        PageHelper.startPage(page, limit);
        List<ContentVo> list = contentDao.findByCatalog(mid);
        PageInfo<ContentVo> paginator = new PageInfo<>(list);
        paginator.setTotal(total);
        return paginator;
    }

    @Override
    public PageInfo<ContentVo> getArticles(String keyword, Integer page, Integer limit) {
        return getArticles(null, keyword, page, limit);
    }

    @Override
    public PageInfo<ContentVo> getArticles(Integer uid, String keyword, Integer page, Integer limit) {
        PageHelper.startPage(page, limit);
        if(StringUtils.isBlank(keyword)){
            return new PageInfo<>(Lists.newArrayList());
        }

        Example example = new Example(ContentVo.class);
        Example.Criteria criteria = example.createCriteria();
        if (null!=uid){
            criteria.andEqualTo("authorId",uid);
        }
        criteria.andEqualTo("type",Types.ARTICLE.getType()).andEqualTo("status",Types.PUBLISH.getType());
        criteria.andLike("title","%" + keyword + "%");
        example.setOrderByClause("created desc");

        example.excludeProperties("content");
        List<ContentVo> contentVos = contentDao.selectByExample(example);

        return new PageInfo<>(contentVos);
    }

    /**
     * * 根据type类型以及status列表分页查询文章
     *      默认查询post类型，publish状态的文章
     *
     * @param type
     * @param conditions
     * @param page
     * @param limit
     * @return
     */
    @Override
    public PageInfo<ContentVo> getArticlesWithTypeAndStatus(Integer uid, String type,List<String> conditions,Integer page, Integer limit) {
        Example example = new Example(ContentVo.class);
        Example.Criteria criteria = example.createCriteria();
        if(StringUtils.isNotBlank(type)){
            criteria.andEqualTo("type",type);
        }else{
            criteria.andEqualTo("type",Types.ARTICLE.getType());
        }
        if(null!=uid){
            criteria.andEqualTo("authorId",uid);
        }

        if(null != conditions && conditions.size()>0){
            criteria.andIn("status",conditions);
        }else {
            List<String> status = Lists.newArrayList();
            status.add(Types.PUBLISH.getType());
            criteria.andIn("status",status);
        }
        //按照修改的时间来排序
        example.setOrderByClause("modified desc");

        //排除content字段
        example.excludeProperties("content");

        PageHelper.startPage(page, limit);
        List<ContentVo> contentVos = contentDao.selectByExample(example);
        return new PageInfo<>(contentVos);
    }

    /**
     * 搜索
     *
     * @param type
     * @param statusList
     * @param categories
     * @param page
     * @param limit
     * @return
     */
    @Override
    public PageInfo<ContentVo> getArticlesWithTitle(Integer uid, String type,List<String> statusList,List<String> categories,Integer page, Integer limit,String title) {
        Example example = new Example(ContentVo.class);
        Example.Criteria criteria = example.createCriteria();
        if(StringUtils.isNotBlank(type)){
            criteria.andEqualTo("type",type);
        }else{
            criteria.andEqualTo("type",Types.ARTICLE.getType());
        }
        if(null!=uid){
            criteria.andEqualTo("authorId",uid);
        }

        if(null != statusList && statusList.size()>0){
            criteria.andIn("status",statusList);
        }else {
            List<String> status = Lists.newArrayList();
            status.add(Types.PUBLISH.getType());
            criteria.andIn("status",status);
        }

        if(null != categories && categories.size()>0){
            criteria.andLike("categories","%" + categories.get(0) + "%");
        }

        if(StringUtils.isNoneBlank(title)){
            criteria.andLike("title","%" + title + "%");
        }
        //按照修改的时间来排序
        example.setOrderByClause("modified desc");

        //排除content字段
        example.excludeProperties("content");

        PageHelper.startPage(page, limit);
        List<ContentVo> contentVos = contentDao.selectByExample(example);
        return new PageInfo<>(contentVos);
    }

    @Override
    @Transactional
    public String deleteByCid(Integer cid) {
        ContentVo contents = this.getContents(cid + "");
        if (null != contents) {
            /*contentDao.deleteByPrimaryKey(cid);
            relationshipService.deleteById(cid, null);*/
            contents.setStatus("delete");
            contentDao.updateByPrimaryKeySelective(contents);

            List<RelationshipVoKey> realationships = relationshipService.getRelationshipById(cid,null);
            for (RelationshipVoKey key:realationships){
                MetaVo metaVo = metaDao.selectByPrimaryKey(key.getMid());

                //更新关联关系
                key.setDelFlag(Boolean.TRUE);
                relationshipService.updateBySelective(key);

                // 更新分类或者标签的引用次数
                if (metaVo!=null && metaVo.getCitationTimes()!=0){
                    metaVo.setCitationTimes(metaVo.getCitationTimes()-1);
                    metaDao.updateByPrimaryKeySelective(metaVo);
                }
            }

            return WebConst.SUCCESS_RESULT;
        }
        return "数据为空";
    }

    @Override
    public void updateCategory(String ordinal, String newCatefory) {
        ContentVo contentVo = new ContentVo();
        contentVo.setCategories(newCatefory);
        /*ContentVoExample example = new ContentVoExample();
        example.createCriteria().andCategoriesEqualTo(ordinal);*/

        Example example1 = new Example(ContentVo.class);
        example1.createCriteria().andEqualTo("categories",ordinal);

        contentDao.updateByExampleSelective(contentVo, example1);
    }

    @Override
    @Transactional
    public String updateArticle(ContentVo contents) {
        if (null == contents) {
            return "文章对象为空";
        }
        if (StringUtils.isBlank(contents.getTitle())) {
            return "文章标题不能为空";
        }
        if (StringUtils.isBlank(contents.getContent())) {
            return "文章内容不能为空";
        }
        int titleLength = contents.getTitle().length();
        if (titleLength > WebConst.MAX_TITLE_COUNT) {
            return "文章标题过长";
        }
        int contentLength = contents.getContent().length();
        if (contentLength > WebConst.MAX_TEXT_COUNT) {
            return "文章内容过长";
        }
        if (null == contents.getAuthorId()) {
            return "请登录后发布文章";
        }
        if (StringUtils.isBlank(contents.getSlug())) {
            contents.setSlug(null);
        }
        int time = DateKit.getCurrentUnixTime();
        contents.setModified(time);
        Integer cid = contents.getCid();
        //获取之前的文章状态
        Example example = new Example(ContentVo.class);
        example.selectProperties("status");
        example.createCriteria().andEqualTo("cid",cid);
        ContentVo oldContentVo = contentDao.selectOneByExample(example);

        contents.setContent(EmojiParser.parseToAliases(contents.getContent()));

        contents = resetContentVo(contents);

        contentDao.updateByPrimaryKeySelective(contents);
        relationshipService.deleteById(cid, null);
        //更新tags
        metasService.saveMetas(contents.getAuthorId(),cid, contents.getTags(), Types.TAG.getType(),contents.getStatus(),oldContentVo.getStatus());
        //更新categories
        metasService.saveMetas(contents.getAuthorId(),cid,contents.getCategories(), Types.CATEGORY.getType(),contents.getStatus(),oldContentVo.getStatus());
        return WebConst.SUCCESS_RESULT;
    }

    /**
     * 文章标签和分类去重
     * @param contents
     * @return
     */
    private static ContentVo resetContentVo(ContentVo contents){
        String tags = contents.getTags();
        String categories = contents.getCategories();

        // tags和categories去重
        try {
            tags = String.join(",",Tools.removeDuplicate(Arrays.asList(tags.split(","))));
            categories = String.join(",",Tools.removeDuplicate(Arrays.asList(categories.split(","))));
            contents.setTags(tags);
            contents.setCategories(categories);
        }catch (Exception e){
            LOGGER.info("去重文章标签,分类发生异常",e);
        }
        return contents;
    }
}
